using System;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly: TagPrefix("DatePicker", "EWS")]
namespace Library.WebControls
{
	[DefaultProperty("Text")]
	[ToolboxData("<{0}:DatePicker runat=server></{0}:DatePicker>")]
	[DefaultEvent("SelectionChanged")]
	[ValidationProperty("TextValue")]
	public class DatePicker : WebControl, INamingContainer
	{
		#region Properties

		public TextBox txtDate = new TextBox();
		public Calendar calDate = new Calendar();
		public Button btnDate = new Button();
		public Panel pnlCalendar = new Panel();

		private enum ViewStateConstants
		{
			ValidationGroup,
			RegularExpression,
			ErrorMessage,
			RegExText,
			CalendarPosition,
			FormatString,
			ExpandLabel,
			CollapseLabel,
			ApplyDefaultStyle,
			CausesValidation,
		}

		/// <summary>
		/// Defines the available display modes of this calendar.
		/// </summary>
		public enum CalendarDisplay
		{
			DisplayRight,
			DisplayBelow
		}

		/// <summary>
		/// Where to display the popup calendar.
		/// </summary>
		[Category("Behaviour")]
		[Localizable(true)]
		public CalendarDisplay CalendarPosition
		{
			get
			{
				if (ViewState[ViewStateConstants.CalendarPosition.ToString()] == null)
				{
					ViewState[ViewStateConstants.CalendarPosition.ToString()] = CalendarDisplay.DisplayRight;
				}
				return (CalendarDisplay)ViewState[ViewStateConstants.CalendarPosition.ToString()];
			}
			set
			{
				ViewState[ViewStateConstants.CalendarPosition.ToString()] = value;
			}
		}

		/// <summary>
		/// Text version of the control's value, for use by ASP.NET validators.
		/// </summary>
		public string TextValue
		{
			get { return txtDate.Text; }
		}

		/// <summary>
		/// Holds the current date value of this control.
		/// </summary>
		[Category("Behaviour")]
		[Localizable(true)]
		[Bindable(true)]
		public DateTime DateValue
		{
			get
			{
				try
				{
					if (txtDate.Text == "") return DateTime.MinValue;

					DateTime val = DateTime.Parse(txtDate.Text);
					return val;
				}
				catch (ArgumentNullException)
				{
					return DateTime.MinValue;
				}
				catch (FormatException)
				{
					return DateTime.MinValue;
				}
			}
			set
			{
				if (value == DateTime.MinValue)
				{
					txtDate.Text = "";
				}
				else
				{
					txtDate.Text = value.ToShortDateString();
				}
			}
		}

		[Category("Behavior"), DefaultValue("")]
		public virtual string ValidationGroup
		{
			get
			{
				if (ViewState[ViewStateConstants.ValidationGroup.ToString()] == null)
				{
					return string.Empty;
				}
				else
				{
					return (string)ViewState[ViewStateConstants.ValidationGroup.ToString()];
				}
			}
			set
			{
				ViewState[ViewStateConstants.ValidationGroup.ToString()] = value;
			}
		}

		/// <summary>
		/// The label of the exand button. Shown when the calendar is hidden.
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("+")]
		[Localizable(true)]
		public string ExpandButtonLabel
		{
			get
			{
				String s = (String)ViewState[ViewStateConstants.ExpandLabel.ToString()];
				return ((s == null) ? "+" : s);
			}
			set
			{
				ViewState[ViewStateConstants.ExpandLabel.ToString()] = value;
			}
		}

		/// <summary>
		/// The label of the collapse button. Shown when the calendar is visible.
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("-")]
		[Localizable(true)]
		public string CollapseButtonLabel
		{
			get
			{
				String s = (String)ViewState[ViewStateConstants.CollapseLabel.ToString()];
				return ((s == null) ? "-" : s);
			}
			set
			{
				ViewState[ViewStateConstants.CollapseLabel.ToString()] = value;
			}
		}

		/// <summary>
		/// Whether to apply the default style. Disable this if you want to apply a custom style, or to use themes and skins
		/// to style the control.
		/// </summary>
		[Category("Appearance")]
		[DefaultValue(true)]
		[Localizable(true)]
		public bool ApplyDefaultStyle
		{
			get
			{
				if (ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] == null)
				{
					ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] = true;
				}
				return (bool)ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()];
			}
			set
			{
				ViewState[ViewStateConstants.ApplyDefaultStyle.ToString()] = value;
			}
		}

		/// <summary>          
		/// Causes Validation          
		/// </summary>          
		[Category("Appearance")]
		[DefaultValue(false)]
		[Localizable(false)]
		public bool CausesValidation
		{
			get
			{
				if (ViewState[ViewStateConstants.CausesValidation.ToString()] == null)
				{
					ViewState[ViewStateConstants.CausesValidation.ToString()] = false;
				}
				return (bool)ViewState[ViewStateConstants.CausesValidation.ToString()];
			}
			set
			{
				ViewState[ViewStateConstants.CausesValidation.ToString()] = value;
				btnDate.CausesValidation = value;
			}
		}

		#endregion

		#region Events

		/// <summary>
		/// A day was selected from the calendar control.
		/// </summary>
		public event EventHandler SelectionChanged;

		protected virtual void OnSelectionChanged()
		{
			if (SelectionChanged != null)   // only raise the event if someone is listening.
			{
				SelectionChanged(this, EventArgs.Empty);
			}
		}

		#endregion

		#region Event Handlers

		/// <summary>
		/// The +/- button was clicked.
		/// </summary>
		protected void btnDate_Click(object sender, System.EventArgs e)
		{
			if (!calDate.Visible)
			{
				// expand the calendar
				calDate.Visible = true;
				txtDate.Enabled = false;
				btnDate.Text = CollapseButtonLabel;
				if (DateValue != DateTime.MinValue)
				{
					calDate.SelectedDate = DateValue;
					calDate.VisibleDate = DateValue;
				}
			}
			else
			{
				// collapse the calendar
				calDate.Visible = false;
				txtDate.Enabled = true;
				btnDate.Text = ExpandButtonLabel;
			}
		}

		/// <summary>
		/// A date was selected from the calendar.
		/// </summary>
		protected void calDate_SelectionChanged(object sender, System.EventArgs e)
		{
			calDate.Visible = false;
			txtDate.Visible = true;
			btnDate.Text = ExpandButtonLabel;
			txtDate.Enabled = true;
			txtDate.Text = calDate.SelectedDate.ToShortDateString();
			OnSelectionChanged();
		}

		#endregion

		/// <summary>
		/// Builds the contents of this control.
		/// </summary>
		protected override void CreateChildControls()
		{
			btnDate.Text = ExpandButtonLabel;
			btnDate.CausesValidation = CausesValidation;
			txtDate.ID = "txtDate";

			calDate.Visible = false;

			if (ApplyDefaultStyle)
			{
				calDate.BackColor = System.Drawing.Color.White;
				calDate.BorderColor = System.Drawing.Color.FromArgb(10066329);
				calDate.CellPadding = 2;
				calDate.DayNameFormat =  System.Web.UI.WebControls.DayNameFormat.Short;
				calDate.Font.Name = "Verdana";
				calDate.Font.Size = FontUnit.Parse("8pt");
				calDate.ForeColor = System.Drawing.Color.Black;
				calDate.Height = new Unit(150, UnitType.Pixel);
				calDate.Width = new Unit(180, UnitType.Pixel);
				calDate.DayHeaderStyle.BackColor = System.Drawing.Color.FromArgb(228, 228, 228);
				calDate.DayHeaderStyle.Font.Size = FontUnit.Parse("7pt");
				calDate.TitleStyle.Font.Bold = true;
				calDate.WeekendDayStyle.BackColor = System.Drawing.Color.FromArgb(255, 255, 204);
			}

			ConnectEventHandlers();

			pnlCalendar.Controls.Add(calDate);
			pnlCalendar.Style["position"] = "absolute";
			pnlCalendar.Style["filter"] = "alpha(opacity=95)";
			pnlCalendar.Style["-moz-opacity"] = ".95";
			pnlCalendar.Style["opacity"] = ".95";
			pnlCalendar.Style["z-index"] = "2";
			pnlCalendar.Style["background-color"] = "White";

			if (CalendarPosition == CalendarDisplay.DisplayBelow)
			{
				pnlCalendar.Style["margin-top"] = "27px";
			}
			else
			{
				pnlCalendar.Style["display"] = "inline";
			}

			Controls.Add(txtDate);
			Controls.Add(pnlCalendar);
			Controls.Add(btnDate);

			base.CreateChildControls();
		}

		/// <summary>
		/// Render the contents of this control.
		/// </summary>
		/// <param name="output">The HtmlTextWriter to use.</param>
		protected override void RenderContents(HtmlTextWriter output)
		{
			switch (CalendarPosition)
			{
				case CalendarDisplay.DisplayRight:
				{
					txtDate.RenderControl(output);
					btnDate.RenderControl(output);
					pnlCalendar.RenderControl(output);
					break;
				}
				case CalendarDisplay.DisplayBelow:
				{
					pnlCalendar.RenderControl(output);
					txtDate.RenderControl(output);
					btnDate.RenderControl(output);
					break;
				}
			}
		}

		/// <summary>
		/// Connect event handlers to events.
		/// </summary>
		private void ConnectEventHandlers()
		{
			btnDate.Click += new System.EventHandler(btnDate_Click);
			calDate.SelectionChanged += new System.EventHandler(calDate_SelectionChanged);
		}

		public override Unit Width
		{
			get
			{
				return base.Width;
			}
			set
			{
				base.Width = value;
				this.txtDate.Width = new Unit(value.Value - (value.Value * 0.25D), value.Type);
				this.btnDate.Width = new Unit(value.Value - (value.Value * 0.75D), value.Type);
			}
		}

	}
}
